package cn.net.autocode.platform.workflow.service;

import cn.hutool.core.util.StrUtil;
import cn.net.autocode.core.utils.UserThreadLocalUtils;
import cn.net.autocode.dbManager.Dao;
import cn.net.autocode.dbManager.IdWorker;
import cn.net.autocode.dbManager.handler.PreparedStatementHandler;
import cn.net.autocode.maths.NumberFormat;
import cn.net.autocode.platform.factory.SpringBeanFactory;
import cn.net.autocode.platform.workflow.WfActionAnnotation;
import cn.net.autocode.platform.workflow.WfAnnotation;
import cn.net.autocode.platform.workflow.WfCancelAnnotation;
import cn.net.autocode.platform.workflow.vo.Workflow;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Slf4j
public class WorkflowServ {
    private final Dao dao;

    private Map<String,Object> workflowMap;

    public WorkflowServ(Dao dao) {
        this.dao = dao;
    }

    /**
     * 创建工作流
     */
    public JSONObject create(String wfCode,String busiId,String wfRecordTitle){

        //获取工作流信息
        JSONObject workflowJSON = dao.queryJSON("select * from autocode_wf where wf_code=?",wfCode);
        if(workflowJSON==null || workflowJSON.isEmpty()){
            throw new RuntimeException("工作流【"+wfCode+"】不存在！");
        }
        String busiTable = workflowJSON.getString("busiTable");
        String statusColumn = workflowJSON.getString("statusField");
        String statusField = PreparedStatementHandler.columnToProperty(statusColumn);

        //获取业务主表的信息，判断所有表是否处于同一个环节
        Map<String,Object> stepMap = dao.queryMapVT("select step_code value,step_name text from autocode_wf_step where wf_code=?",wfCode);
        String sql = "select * from "+busiTable+" where id = ?";
        JSONObject busi = dao.queryJSON(sql,busiId);
        JSONObject wfRecord =  new JSONObject();
        wfRecord.put("wfCode",wfCode);
        wfRecord.put("busiId",busi.getString("id"));
        wfRecord.put("id",IdWorker.ulid());
        wfRecord.put("creator",UserThreadLocalUtils.getUserName());
        wfRecord.put("createFullname",UserThreadLocalUtils.getRealName());
        wfRecord.put("orgCode",UserThreadLocalUtils.getOrgCode());
        wfRecord.put("busiTable",busiTable);
        wfRecord.put("createTime",LocalDateTime.now());
        wfRecord.put("status","Active");
        wfRecord.put("wfName",workflowJSON.getString("label"));
        wfRecord.put("wfRecordTitle",wfRecordTitle);

        //获取流程单号
        LocalDate localDate = LocalDate.now();
        String pre = wfCode+"-"+localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String maxWfRecordCode = dao.queryValue("select max(wf_record_code) from autocode_wf_record where wf_code=? and wf_record_code like ?",String.class,wfCode,pre+"%");
        if(maxWfRecordCode==null||maxWfRecordCode.isBlank()){
            String recordCode = pre+"-0001";
            wfRecord.put("wfRecordCode",recordCode);
        }else{
            String recordCode = pre+"-"+ NumberFormat.IntFormat(Integer.parseInt(maxWfRecordCode.replace(pre+"-",""))+1,"0000");
            wfRecord.put("wfRecordCode",recordCode);
        }
        dao.createJSON(wfRecord,"autocode_wf_record");

        JSONObject wfRecrodStep = new JSONObject();
        wfRecrodStep.put("id",IdWorker.ulid());
        wfRecrodStep.put("wfRecordId",wfRecord.getString("id"));
        wfRecrodStep.put("stepCode",busi.getString(statusField));
        wfRecrodStep.put("stepName",stepMap.get(busi.getString(statusField)));
        wfRecrodStep.put("status","Active");
        wfRecrodStep.put("fromTime",LocalDateTime.now());
        wfRecrodStep.put("auditUsername",UserThreadLocalUtils.getUserName());
        wfRecrodStep.put("auditFullname",UserThreadLocalUtils.getRealName());
        wfRecrodStep.put("isStep","Y");
        dao.createJSON(wfRecrodStep,"autocode_wf_record_step");
        if("Y".equals(workflowJSON.getString("preAuth"))){
            dao.executeUpdate("insert into autocode_wf_record_step_user(id,wf_record_step_id,username,status) values(?,?,?,?)",IdWorker.ulid(),wfRecrodStep.getString("id"),UserThreadLocalUtils.getUserName(),"Active");
        }
        return wfRecord;
    }

    /**
     * 创建工作流
     */
    @Transactional
    public String delete(String wfCode,String busiId){

        //获取业务主表的信息，判断所有表是否处于同一个环节
        String recordId = dao.queryValue("select id from autocode_wf_record where wf_code=? and busi_id=?",String.class,wfCode,busiId);
        if (recordId!=null&&!recordId.isBlank()){
            dao.executeUpdate("delete from autocode_wf_record_step_user t1 where exists(select 1 from autocode_wf_record_step t2 where t1.wf_record_step_id=t2.id and t2.wf_record_id=?)",recordId);
            dao.executeUpdate("delete from autocode_wf_record_step where wf_record_id=?",recordId);
            dao.executeUpdate("delete from autocode_wf_record where id=?",recordId);
        }
        return "success";
    }

    public void before(Workflow workflow){

        //获取处理规则
        String actionId = workflow.getAction().getActionId();
        JSONArray rules = dao.queryJSONArray("select * from autocode_wf_step_action_rule where action_id=? order by sort_no",actionId);
        for(int i=0;i<rules.size();i++){
            JSONObject rule = rules.getJSONObject(i);
            JSONArray ruleDetail = dao.queryJSONArray("select * from autocode_wf_rule_detail where rule_id=? order by sort_no",rule.getString("id"));
            rule.put("ruleDetail",ruleDetail);
        }

        //根据处理规则，获取下一步的操作步骤
        List<Workflow.Business> businessList = workflow.getBusinessList();
        for(Workflow.Business business:businessList){
            JSONObject busiData = business.getData();
            //进行规则判断
            for(int j=0;j<rules.size();j++){
                JSONObject rule = rules.getJSONObject(j);
                JSONArray ruleDetails = rule.getJSONArray("ruleDetail");
                boolean flag = false;
                for(int k=0;k<ruleDetails.size();k++){
                    JSONObject ruleDetail = ruleDetails.getJSONObject(k);
                    String fieldName = PreparedStatementHandler.columnToProperty(ruleDetail.getString("fieldName"));
                    String operator = ruleDetail.getString("operator");
                    String limitValue = ruleDetail.getString("limitValue");
                    if (!busiData.containsKey(fieldName)){
                        flag = false;
                        break;
                    }
                    Object busiValue = busiData.get(fieldName);
                    if (busiValue==null){
                        flag = false;
                        break;
                    }
                    String strValue;
                    if(busiValue instanceof Date date){
                        SimpleDateFormat dateFormat;
                        if(limitValue.length()==10){
                            dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        }else{
                            dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        }
                        strValue = dateFormat.format(date);
                    }else if(busiValue instanceof String str){
                        strValue = str;
                    }else if(busiValue instanceof Double dd){
                        if(dd == Math.floor(dd)){
                            strValue = String.valueOf(dd.longValue());
                        }else{

                            DecimalFormat df = new DecimalFormat("#.#######");
                            strValue = df.format(dd);
                        }
                    }else if(busiValue instanceof BigDecimal bd){
                        strValue =bd.toPlainString();
                    }else{
                        strValue = busiValue.toString();
                    }

                    flag = switch (operator){
                        case "=" -> strValue.equals(limitValue);
                        case "<=" -> strValue.compareTo(limitValue) <= 0;
                        case "<" -> strValue.compareTo(limitValue) < 0;
                        case ">" -> strValue.compareTo(limitValue) > 0;
                        case ">=" -> strValue.compareTo(limitValue) >= 0;
                        case "!=" -> !strValue.equals(limitValue);
                        default -> false;
                    };
                    if (!flag){
                        break;
                    }
                }

                if (flag){
                    business.setToStepcode(rule.getString("toStepcode"));
                    break;
                }
            }
        }
    }

    public void action(Workflow workflow,String point){
        if(!"after".equalsIgnoreCase(point)){
            point="before";
        }
        if (this.workflowMap==null){
            this.init();
        }

        String wfCode = workflow.getWfCode();
        Object object = this.workflowMap.get(wfCode);
        if(object!=null){
            Method[] methods = object.getClass().getMethods();
            for (Method method : methods) {
                if (method.getParameterCount()==1
                        && method.getParameterTypes()[0].getName().equals("cn.net.autocode.platform.workflow.vo.Workflow$Business")
                        && method.isAnnotationPresent(WfActionAnnotation.class)
                ) {
                    WfActionAnnotation annotation = method.getAnnotation(WfActionAnnotation.class);
                    if (annotation.stepCode().equals(workflow.getStepCode()) && annotation.actionCode().equals(workflow.getActionCode()) && annotation.point().equals(point)){
                        try {
                            for(Workflow.Business business:workflow.getBusinessList()){
                                method.invoke(object,business);
                            }
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            log.error(e.getMessage());
                            throw new RuntimeException(e.getCause().getMessage());
                        }
                        break;
                    }
                }
            }
        }
    }

    public JSONArray after(Workflow workflow){
        //获取步骤映射
        Map<String,Object> stepMap = dao.queryMapVT("select step_code value,step_name text from autocode_wf_step where wf_code=?",workflow.getWfCode());
        //记录审核记录
        List<Workflow.Business> businessList = workflow.getBusinessList();

        JSONArray result = new JSONArray();
        for(Workflow.Business business:businessList){
            String busiId = business.getBusiId();
            //修改业务表信息
            dao.executeUpdate("update "+workflow.getBusiTable()+" set "+workflow.getStatusColumn()+"=? where id=?",business.getToStepcode(),busiId);

            //如果是退回，则做退回标记
            if("Y".equals(workflow.getAction().getIsReject())){
                dao.executeUpdate("update "+workflow.getBusiTable()+" set "+workflow.getRejectColumn()+"=? where id=?","Y",busiId);
            }

            //修改流程记录
            JSONObject wfRecord = dao.queryJSON("select * from autocode_wf_record where wf_code=? and busi_id=?",workflow.getWfCode(),busiId);
            if(wfRecord.isEmpty()){
                this.create(workflow.getWfCode(),busiId,null);
                result.add(new JSONObject());
            }else{
                //获取当前环节
                JSONObject wfRecordStep = dao.queryJSON("select * from autocode_wf_record_step where wf_record_id=? and step_code=? and status='Active'",wfRecord.getString("id"),workflow.getStepCode());
                if (wfRecordStep.isEmpty()){
                    continue;
                }
                //判定是否会签,会签功能暂时没有使用
                String multiaudit = wfRecordStep.getString("multiaudit");

                String preAuth = workflow.getPreAuth();
                if (preAuth.equalsIgnoreCase("Y")){
                    //判定是否有操作权限
                    int num = dao.queryValue("select count(*) from autocode_wf_record_step_user where wf_record_step_id=? and username=? and status='Active'",Integer.class,wfRecordStep.getString("id"),UserThreadLocalUtils.getUserName());
                    if (num==0){
                        throw new RuntimeException("你没有该流程的操作权限！");
                    }
                }

                LocalDateTime curTime = LocalDateTime.now();
                wfRecordStep.put("actionCode",workflow.getAction().getActionCode());
                wfRecordStep.put("actionName",workflow.getAction().getActionName());
                wfRecordStep.put("auditTime", curTime);
                wfRecordStep.put("auditComment",workflow.getComment());
                wfRecordStep.put("auditUsername", UserThreadLocalUtils.getUserName());
                wfRecordStep.put("auditFullname",UserThreadLocalUtils.getRealName());
                wfRecordStep.put("auditResult",workflow.getAction().getIsReject().equals("Y")?"reject":"pass");
                wfRecordStep.put("toStepcode",business.getToStepcode());
                wfRecordStep.put("toStepname",stepMap.get(business.getToStepcode()));
                wfRecordStep.put("toTime",curTime);
                wfRecordStep.put("status","close");
                dao.updateJSON(wfRecordStep,"autocode_wf_record_step");
                dao.executeUpdate("delete from autocode_wf_record_step_user where wf_record_step_id=?",wfRecordStep.getString("id"));

                //进入下一环节
                String toStepcode = business.getToStepcode();
                JSONObject nextStep = dao.queryJSON("select * from autocode_wf_step where wf_code=? and step_code=?",workflow.getWfCode(),toStepcode);
                if (nextStep.isEmpty()){
                    if (preAuth.equalsIgnoreCase("Y")){
                        throw new RuntimeException("流程配置异常，没有找到下一环节信息，不能继续进行审批！");
                    }else{
                        continue;
                    }

                }
                //记录下一环节信息
                nextStep.put("wfStepId",nextStep.getString("id"));
                nextStep.put("id", IdWorker.ulid());
                nextStep.put("fromStepcode", workflow.getStepCode());
                nextStep.put("status","Active");
                nextStep.put("fromTime",curTime);
                nextStep.put("isStep","Y");
                nextStep.put("wfRecordId",wfRecord.getString("id"));

                String nextMultiaudit = nextStep.getString("multiaudit");
                if(nextMultiaudit==null || nextMultiaudit.isBlank()){
                    nextMultiaudit="N";
                }

                nextStep.put("multiaudit",nextMultiaudit);

                dao.createJSON(nextStep,"autocode_wf_record_step");

                //确定是否需要预设人员
                if (preAuth.equalsIgnoreCase("Y") && !"Y".equals(nextStep.getString("endStep"))){
                    String auditType = nextStep.getString("auditType");
                    String auditOrgan = nextStep.getString("auditOrgan");
                    //寻找下一步人员
                    if ("default".equalsIgnoreCase(auditOrgan)){
                        auditOrgan=wfRecord.getString("orgCode");
                    }
                    if("none".equalsIgnoreCase(auditType)){
                        throw new RuntimeException("流程配置异常，没有指定下一环节审批人，不能继续进行审批！");
                    }

                    List<String> userNames = new ArrayList<>();

                    if("assign".equalsIgnoreCase(auditType)){
                        JSONArray auditUsers = workflow.getAuditUsers();
                        if(auditUsers==null || auditUsers.isEmpty()){
                            throw new RuntimeException("流程配置异常，没有指定下一环节审批人，不能继续进行审批！");
                        }
                        for(int i=0;i<auditUsers.size();i++){
                            String username = auditUsers.getString(i);
                            userNames.add(username);
                        }
                    }else if("creater".equalsIgnoreCase(auditType)){
                        userNames.add(wfRecord.getString("creator"));
                    }else if("dept".equalsIgnoreCase(auditType)){
                        String deptId = dao.queryValue("select dept_id from "+workflow.getBusiTable()+" where id=?",String.class,busiId);
                        if (deptId==null || deptId.isBlank()){
                            throw new RuntimeException("没有登记创建人部门！");
                        }
                        String bmfzr = dao.queryValue("select bmfzr from sys_departments where id=?",String.class,deptId);
                        if (bmfzr==null || bmfzr.isBlank()){
                            throw new RuntimeException("没有设置部门负责人，不能提交到部门负责人审核！");
                        }
                        userNames.add(bmfzr);
                    }else if("supv".equalsIgnoreCase(auditType)){
                        String deptId = dao.queryValue("select dept_id from "+workflow.getBusiTable()+" where id=?",String.class,busiId);
                        if (deptId==null || deptId.isBlank()){
                            throw new RuntimeException("没有登记创建人部门！");
                        }
                        List<String> fgld = dao.queryListValue("select username from sys_department_leader where dept_id=? and leader_type=?",String.class,deptId,"fgld");
                        if (fgld==null || fgld.isEmpty()){
                            throw new RuntimeException("没有设置分管领导，不能提交到分管领导审核！");
                        }
                        userNames.addAll(fgld);
                    }else if("xcdb".equalsIgnoreCase(auditType)){
                        String deptId = dao.queryValue("select dept_id from "+workflow.getBusiTable()+" where id=?",String.class,busiId);
                        if (deptId==null || deptId.isBlank()){
                            throw new RuntimeException("没有登记创建人部门！");
                        }
                        List<String> xcdb = dao.queryListValue("select username from sys_department_leader where dept_id=? and leader_type=?",String.class,deptId,"xcdb");
                        if (xcdb==null || xcdb.isEmpty()){
                            throw new RuntimeException("没有设置现场代表，不能提交到现场代表审核！");
                        }
                        userNames.addAll(xcdb);
                    }else if("xcfg".equalsIgnoreCase(auditType)){
                        String deptId = dao.queryValue("select dept_id from "+workflow.getBusiTable()+" where id=?",String.class,busiId);
                        if (deptId==null || deptId.isBlank()){
                            throw new RuntimeException("没有登记创建人部门！");
                        }
                        List<String> xcfg = dao.queryListValue("select username from sys_department_leader where dept_id=? and leader_type=?",String.class,deptId,"xcfg");
                        if (xcfg==null || xcfg.isEmpty()){
                            throw new RuntimeException("没有设置现场分管，不能提交到现场分管审核！");
                        }
                        userNames.addAll(xcfg);
                    }else if("organ".equalsIgnoreCase(auditType)){
                        //manager
                        String manager = dao.queryValue("select manager from sys_organ where code=?",String.class,auditOrgan);
                        if (manager==null || manager.isBlank()){
                            throw new RuntimeException("没有设置公司负责人，不能提交到公司负责人审批！");
                        }
                    }else if("roleUser".equalsIgnoreCase(auditType)){
                        JSONArray array = dao.queryJSONArray("select * from autocode_wf_step_users where wf_step_id=?",nextStep.getString("wfStepId"));
                        List<String> roeUsers = new ArrayList<>();
                        for(int i=0;i<array.size();i++){
                            JSONObject stepUser = array.getJSONObject(i);
                            String stepAuditType = stepUser.getString("auditType");
                            String userName = stepUser.getString("username");
                            String roleId = stepUser.getString("roleId");
                            if("user".equalsIgnoreCase(stepAuditType)){
                                roeUsers.add(userName);
                            }else if("role".equalsIgnoreCase(stepAuditType)){
                                List<String> roleUsers = dao.queryListValue("select username  from sys_role_users where role_id=? and rog_code=?",String.class,roleId,auditOrgan);
                                roeUsers.addAll(roleUsers);
                            }else if("ugroup".equalsIgnoreCase(stepAuditType)){
                                List<String> ugroupUsers = dao.queryListValue("select username from sys_ugroup_users t1,sys_ugroup t2 where t1.ugroup_id=t2.id and t2.id=? and t2.org_code=?",String.class,roleId,auditOrgan);
                                roeUsers.addAll(ugroupUsers);
                            }
                        }
                        if (roeUsers.isEmpty()){
                            throw new RuntimeException("没有找到下一环节审批人，不能进行提交！");
                        }
                        for (String userName : roeUsers){
                            if (!userNames.contains(userName)){
                                userNames.add(userName);
                            }
                        }
                    }
                    //设置审批人信息
                    for (String userName : userNames){
                        dao.executeUpdate("insert into autocode_wf_record_step_user(id,wf_record_step_id,username,status) values(?,?,?,?)",IdWorker.ulid(),nextStep.getString("id"),userName,"Active");
                    }
                    //设置审批人
                    List<String> fullnameList = dao.queryListValue("select fullname from sys_users where username in (?)",String.class,userNames);
                    String auditFullname = String.join("", fullnameList);
                    dao.executeUpdate("update autocode_wf_record_step set audit_fullname=? where id=?",auditFullname,nextStep.getString("id"));
                    nextStep.put("auditFullname",auditFullname);
                }

                //判断是否结束环节
                if("Y".equals(nextStep.getString("endStep"))){
                    dao.executeUpdate("update autocode_wf_record_step set status='close',to_time=?,audit_time=?,audit_username=?,audit_fullname=? where id=?",curTime,curTime,UserThreadLocalUtils.getUserName(),UserThreadLocalUtils.getRealName(),nextStep.getString("id"));
                    dao.executeUpdate("update autocode_wf_record set status='finish',finish_time=? where id=?",curTime,nextStep.getString("id"));
                }
                result.add(nextStep);
            }
        }
        return result;
    }

    public void cancel(Workflow workflow){
        String cancelStatus = "Cancel";
        String cancelName = "流程终止";

        //记录审核记录
        List<Workflow.Business> businessList = workflow.getBusinessList();

        for(Workflow.Business business:businessList){
            String busiId = business.getBusiId();
            //修改业务表信息
            dao.executeUpdate("update "+workflow.getBusiTable()+" set "+workflow.getStatusColumn()+"=? where id=?",cancelStatus,busiId);
            //修改流程记录
            JSONObject wfRecord = dao.queryJSON("select * from autocode_wf_record where wf_code=? and busi_id=?",workflow.getWfCode(),busiId);
            if(wfRecord!=null && !wfRecord.isEmpty()){
                //获取当前环节
                JSONArray  wfRecordStepArray= dao.queryJSONArray("select * from autocode_wf_record_step where wf_record_id=? and status='Active'",wfRecord.getString("id"));
                LocalDateTime curTime = LocalDateTime.now();
                for(int i=0;i<wfRecordStepArray.size();i++){
                    JSONObject wfRecordStep = wfRecordStepArray.getJSONObject(i);
                    wfRecordStep.put("actionCode",cancelStatus);
                    wfRecordStep.put("actionName",cancelName);
                    wfRecordStep.put("auditTime", curTime);
                    wfRecordStep.put("auditComment",workflow.getComment());
                    wfRecordStep.put("auditUsername", UserThreadLocalUtils.getUserName());
                    wfRecordStep.put("auditResult",cancelStatus);
                    wfRecordStep.put("toStepcode",cancelStatus);
                    wfRecordStep.put("toStepname",cancelName);
                    wfRecordStep.put("toTime",curTime);
                    wfRecordStep.put("status","close");
                    dao.updateJSON(wfRecordStep,"autocode_wf_record_step");
                }

                //记录终止环节
                JSONObject nextStep = new JSONObject();

                nextStep.put("id", IdWorker.ulid());
                nextStep.put("fromStepcode", workflow.getStepCode());
                nextStep.put("status","close");
                nextStep.put("fromTime",curTime);
                nextStep.put("wfRecordId",wfRecord.getString("id"));
                nextStep.put("stepcode",cancelStatus);
                nextStep.put("stepName",cancelName);
                nextStep.put("multiaudit","N");
                nextStep.put("wfCode",workflow.getWfCode());
                nextStep.put("toTime",curTime);
                nextStep.put("auditTime",curTime);
                nextStep.put("auditUsername",UserThreadLocalUtils.getUserName());
                dao.createJSON(nextStep,"autocode_wf_record_step");

                //判断是否结束环节
                dao.executeUpdate("update autocode_wf_record set status=?,finish_time=? where id=?",cancelStatus,curTime,nextStep.getString("id"));
            }
        }
    }

    public void cancelDeal(Workflow workflow,String point){

        if(!"after".equalsIgnoreCase(point)){
            point="before";
        }

        //获取处理规则
        if (this.workflowMap==null){
            this.init();
        }

        String wfCode = workflow.getWfCode();
        Object object = this.workflowMap.get(wfCode);
        if(object!=null){
            Method[] methods = object.getClass().getMethods();
            for (Method method : methods) {
                if (method.getParameterCount()==1
                        && method.getParameterTypes()[0].getName().equals("cn.net.autocode.platform.workflow.vo.Workflow$Business")
                        && method.isAnnotationPresent(WfCancelAnnotation.class)
                ) {
                    WfCancelAnnotation annotation = method.getAnnotation(WfCancelAnnotation.class);
                    if (annotation.point().equals(point)){
                        try {
                            for(Workflow.Business business:workflow.getBusinessList()){
                                method.invoke(object,business);
                            }
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            log.error(e.getMessage());
                            throw new RuntimeException(e.getCause().getMessage());
                        }
                        break;
                    }
                }
            }
        }

    }


    private void init(){
        this.workflowMap = new HashMap<>();
        Map<String,Object> beans = SpringBeanFactory.getBeansByAnnotation(WfAnnotation.class);
        for(Object object:beans.values()){
            WfAnnotation wfAnnotation = object.getClass().getAnnotation(WfAnnotation.class);
            String wfCode = wfAnnotation.wfCode();
            this.workflowMap.put(wfCode,object);
        }
    }

    public String validate(JSONObject param, Workflow workflow){

        String wfCode = param.getString("wfCode");
        String actionCode = param.getString("actionCode");
        String password = param.getString("password");
        String comment = param.getString("comment");
        String stepCode = param.getString("stepCode");
        JSONArray auditUsers = param.getJSONArray("auditUsers");

        workflow.setWfCode(wfCode);
        workflow.setActionCode(actionCode);
        workflow.setComment(comment);
        workflow.setPassword(wfCode);
        workflow.setStepCode(stepCode);
        workflow.setAuditUsers(auditUsers);

        //必传参数判断
        if(StrUtil.isBlank(wfCode)||StrUtil.isBlank(stepCode)||StrUtil.isBlank(actionCode)){
            return "工作流代码【wfCode】、当前环节【stepCode】、动作代码【actionCode】不能为空！";
        }

        //业务主键判断
        List<String> busiIds = new ArrayList<>();
        if(!param.containsKey("busiId") || param.get("busiId")==null){
            return "业务表ID值【busiId】不能为空！";
        }else{
            Object busiId = param.get("busiId");
            if (busiId instanceof JSONArray array){
                if (array.isEmpty()){
                    return "业务表ID值【busiId】不能为空！";
                }else{
                    for(int i=0;i<array.size();i++){
                        busiIds.add(array.getString(i));
                    }
                }
            }else{
                if (StrUtil.isBlankIfStr(busiId)){
                    return "业务表ID值【busiId】不能为空！";
                }else{
                    busiIds.add(busiId.toString());
                }
            }
        }


        //进行用户名、密码验证
        if(StrUtil.isNotBlank(password)){
            String passwrd = dao.queryValue("select passwrd from sys_users where username=?", String.class,UserThreadLocalUtils.getUserName());
            if(!BCrypt.checkpw(password,passwrd)){
                return "用户密码错误！";
            }
        }

        //获取工作流信息
        JSONObject workflowJSON = dao.queryJSON("select * from autocode_wf where wf_code=?",wfCode);
        if (workflowJSON.isEmpty()){
            return "没有找到工作流配置，请检查是否存在代码为【"+wfCode+"】的工作流！";
        }
        String busiTable = workflowJSON.getString("busiTable");
        String statusColumn = workflowJSON.getString("statusField");
        String statusField = PreparedStatementHandler.columnToProperty(statusColumn);
        workflow.setBusiTable(busiTable);
        workflow.setStatusColumn(statusColumn);
        workflow.setStatusField(statusField);
        workflow.setRejectColumn(workflowJSON.getString("rejectField"));
        workflow.setPreAuth(workflowJSON.getString("preAuth"));


        //获取业务主表的信息，判断所有表是否处于同一个环节
        String sql = "select * from "+busiTable+" where id in (?)";
        JSONArray busiArray = dao.queryJSONArray(sql,busiIds);
        if (busiArray.isEmpty()){
            return "没有查询到提交的数据，请确认wfCode与busiId值是否正确！";
        }

        for(int i=0;i<busiArray.size();i++){
            JSONObject busi = busiArray.getJSONObject(i);
            if(!busi.containsKey(statusField)){
                return "没有查询到状态字段，请确认流程配置是否正确！";
            }

            if (!stepCode.equals(busi.getString(statusField))){
                return "提交的数据不处于当前环节，请刷新页面，确认是否重复提交！";
            }
        }

        workflow.setStepCode(stepCode);

        //获取当前操作的环节
        JSONObject actionJSON = dao.queryJSON("select * from autocode_wf_step_actions where wf_code=? and step_code=? and action_code=?",wfCode,stepCode,actionCode);
        if (actionJSON.isEmpty()){
            return "没有找到对应的操作信息，请检查工作流配置是否正确！";
        }
        Workflow.Action action = workflow.new Action();
        action.setActionCode(actionCode);
        action.setActionId(actionJSON.getString("id"));
        action.setActionName(actionJSON.getString("actionName"));
        String isReject = "Y".equals(actionJSON.getString("isreject"))?"Y":"N";
        action.setIsReject(isReject);
        action.setRequireComment("Y".equals(actionJSON.getString("requireComment"))?"Y":"N");
        workflow.setAction(action);

        if (action.getRequireComment().equals("Y")&&StrUtil.isBlank(comment)){
            return "审批意见不能为空！";
        }

        //处理业务数据
        List<Workflow.Business> businessList = new ArrayList<>();
        for(int i=0;i<busiArray.size();i++){
            JSONObject busiJson = busiArray.getJSONObject(i);
            Workflow.Business business = workflow.new Business();
            business.setBusiId(busiJson.getString("id"));
            business.setStatus(busiJson.getString(statusField));
            business.setToStepcode(actionJSON.getString("toStepcode"));
            business.setData(busiJson);
            businessList.add(business);
        }
        workflow.setBusinessList(businessList);

        return "success";
    }

    public String cancelValidate(JSONObject param, Workflow workflow){

        String wfCode = param.getString("wfCode");
        String password = param.getString("password");
        String comment = param.getString("comment");

        workflow.setWfCode(wfCode);
        workflow.setComment(comment);
        workflow.setPassword(wfCode);

        //必传参数判断
        if(StrUtil.isBlank(wfCode)){
            return "工作流代码【wfCode】不能为空！";
        }

        //业务主键判断
        List<String> busiIds = new ArrayList<>();
        if(!param.containsKey("busiId") || param.get("busiId")==null){
            return "业务表ID值【busiId】不能为空！";
        }else{
            Object busiId = param.get("busiId");
            if (busiId instanceof JSONArray array){
                if (array.isEmpty()){
                    return "业务表ID值【busiId】不能为空！";
                }else{
                    for(int i=0;i<array.size();i++){
                        busiIds.add(array.getString(i));
                    }
                }
            }else{
                if (StrUtil.isBlankIfStr(busiId)){
                    return "业务表ID值【busiId】不能为空！";
                }else{
                    busiIds.add(busiId.toString());
                }
            }
        }

        if (StrUtil.isBlank(comment)){
            return "流程终止原因不能为空！";
        }


        //进行用户名、密码验证
        if(StrUtil.isNotBlank(password)){
            String passwrd = dao.queryValue("select passwrd from sys_users where username=?", String.class,UserThreadLocalUtils.getUserName());
            if(!BCrypt.checkpw(password,passwrd)){
                return "用户密码错误！";
            }
        }

        //获取工作流信息
        JSONObject workflowJSON = dao.queryJSON("select * from autocode_wf where wf_code=?",wfCode);
        if (workflowJSON.isEmpty()){
            return "没有找到工作流配置，请检查是否存在代码为【"+wfCode+"】的工作流！";
        }
        String busiTable = workflowJSON.getString("busiTable");
        String statusColumn = workflowJSON.getString("statusField");
        String statusField = PreparedStatementHandler.columnToProperty(statusColumn);
        workflow.setBusiTable(busiTable);
        workflow.setStatusColumn(statusColumn);
        workflow.setStatusField(statusField);
        workflow.setRejectColumn(workflowJSON.getString("rejectField"));

        //获取业务主表的信息，判断所有表是否处于同一个环节
        String sql = "select * from "+busiTable+" where id in (?)";
        JSONArray busiArray = dao.queryJSONArray(sql,busiIds);
        if (busiArray.isEmpty()){
            return "没有查询到提交的数据，请确认wfCode与busiId值是否正确！";
        }

        for(int i=0;i<busiArray.size();i++){
            JSONObject busi = busiArray.getJSONObject(i);
            if(!busi.containsKey(statusField)){
                return "没有查询到状态字段，请确认流程配置是否正确！";
            }

            if ("Cancel".equalsIgnoreCase(busi.getString(statusField))){
                return "流程已终止，请刷新页面，确认是否重复提交！";
            }
        }

        //处理业务数据
        List<Workflow.Business> businessList = new ArrayList<>();
        for(int i=0;i<busiArray.size();i++){
            JSONObject busiJson = busiArray.getJSONObject(i);
            Workflow.Business business = workflow.new Business();
            business.setBusiId(busiJson.getString("id"));
            business.setStatus(busiJson.getString(statusField));
            business.setData(busiJson);
            businessList.add(business);
        }
        workflow.setBusinessList(businessList);

        return "success";
    }
}
